/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <memory>
#include <unordered_map>
#include <string.h>
#include <vector>
#include <unistd.h>
#include "iotc_event.h"
#include "iotc_oh_ble.h"
#include "iotc_oh_wifi.h"
#include "iotc_oh_sle.h"
#include "iotc_oh_sdk.h"
#include "iotc_oh_device.h"
#include "iotc_errcode.h"
#include "sle_conn_device_info.h"
#include "iotc_json.h"

#include "securec.h"
#include "cJSON.h"
#include "iotc_log.h"
#include "parameter.h"
#include "util.h"
#include "iot_connect_log.h"
#include "ohos_bt_gap.h"

#include "iotc_wifi.h"
#include "station_controller.h"
#include "control_value.h"
#include "leaker_detector.h"
#include "sle_thing_model_define.h"
#include "station_factory.h"
#include "leaker_factory.h"
#include "control_factory.h"
#include "timer_mgr.h"
#include "ohos_bt_gap.h"
#include "wifi_device.h"
#include "control_value.h"
namespace OHOS {
namespace iotConnect {

#if IOTC_CONF_AILIFE_SUPPORT != 0
#define HILINK_PSK_LEN 16
#define PINCODE_LEN 8
#endif

#define ADV_TIMEOUT UINT32_MAX

#define DEMO_LOG(...) HILOGI(__VA_ARGS__)

const std::string THING_MODEL_STATION = "1007";
const std::string THING_MODEL_LEAKER = "2001";
const std::string THING_MODEL_CONTROL = "2002";
constexpr int DELAY_MS = 1000 * 1000;  // 1秒延迟
IotcDeviceInfo DEV_INFO = {
    .sn = "FFEE3333",
#if IOTC_CONF_AILIFE_SUPPORT
    .prodId = "2EKT",
#else
    .prodId = "00007",
#endif
    .subProdId = "",
    .model = "STATION",
#if IOTC_CONF_AILIFE_SUPPORT
    .devTypeId = "094",
#else
    .devTypeId = "1007",
#endif
    .devTypeName = "STATION",
    .manuId = "104",
    .manuName = "OpenValley",
    .devName = "STATION1",
    .fwv = "1.0.0",
    .hwv = "1.0.0",
    .swv = "1.0.0",
    .protType = IOTC_PROT_TYPE_BLE_AND_WIFI,
};

static const IotcServiceInfo SVC_INFO[] = {{"devInfo", "devInfo"}, {"wifiInfo", "wifInfo"}, {"sleInfo", "sleInfo"},
    {"configurationManagement", "configurationManagement"}, {"cpu", "cpu"}, {"os", "os"}, {"ota", "ota"},
    {"restart", "restart"}, {"factoryReset", "factoryReset"}, {"serviceList", "serviceList"}};

const char *PIN_CODE = "01234567";

const uint8_t AC_KEY[IOTC_AC_KEY_LEN] = {0x49, 0x3F, 0x45, 0x4A, 0x3A, 0x72, 0x38, 0x7B, 0x36, 0x32, 0x50, 0x3C, 0x49,
    0x39, 0x62, 0x38, 0x72, 0xCB, 0x6D, 0xC5, 0xAE, 0xE5, 0x4A, 0x82, 0xD3, 0xE5, 0x6D, 0xF5, 0x36, 0x82, 0x62, 0xEB,
    0x89, 0x30, 0x6C, 0x88, 0x32, 0x56, 0x23, 0xFD, 0xB8, 0x67, 0x90, 0xA7, 0x7B, 0x61, 0x1E, 0xAE};

static bool g_switch = false;

void SetScreenState(bool isScreenOn)
{
    g_switch = isScreenOn;
}

#if IOTC_CONF_AILIFE_SUPPORT
static int32_t ReportAll(void);

static int32_t DevTimePutCharState(const IotcServiceInfo *svc, const char *data, uint32_t len)
{
    DEMO_LOG("DevTimePutCharState in");
    if (data == NULL || len == 0) {
        return -1;
    }

    ReportAll();
    return 0;
}
#endif

static int32_t IotcDataHandler(const IotcCharState state[], uint32_t num, std::vector<std::string> &out,
    ThingModelPutOrGet flag = ThingModelPutOrGet::GET)
{
#if IOTC_CONF_DEV_TYPE == 2
    if (flag == ThingModelPutOrGet::GET) {
        out.resize(num);
    }

    for (uint32_t i = 0; i < num; ++i) {
        if (strcmp(state[i].svcId, "snw") == 0) {
            std::shared_ptr<AbstractFactory> devFac = std::make_shared<StationFactory>();
            std::shared_ptr<AbstractDevice> devIns = devFac->CreateDeviceInstance();

            if (flag == ThingModelPutOrGet::GET) {
                std::string tempOut;
                devIns->InternalHandler(state[i], tempOut, flag);
                out[i] = tempOut;
                DEMO_LOG("get value, out:%{public}s", out[i].c_str());
            } else {
                std::string dummyOut;
                devIns->InternalHandler(state[i], dummyOut, flag);
            }
            break;
        }

        IotcDeviceInfo *devInfo = NULL;
        if (SLE_BRIDGE_SUCCESS != IotcOhFindDeviceInfo(state[i].devId, (void **)&devInfo)) {
            DEMO_LOG("get devTypeId error");
            continue;
        }
        if (std::string(devInfo->devTypeId) == THING_MODEL_STATION) {
            std::shared_ptr<AbstractFactory> devFac = std::make_shared<StationFactory>();
            std::shared_ptr<AbstractDevice> devIns(devFac->CreateDeviceInstance());

            if (flag == ThingModelPutOrGet::GET) {
                std::string tempOut;
                devIns->InternalHandler(state[i], tempOut, flag);
                out[i] = tempOut;
            } else {
                std::string dummyOut;
                devIns->InternalHandler(state[i], dummyOut, flag);
            }
        } else if (std::string(devInfo->devTypeId) == THING_MODEL_LEAKER) {
            std::shared_ptr<AbstractFactory> devFac = std::make_shared<LeakerFactory>();
            std::shared_ptr<AbstractDevice> devIns(devFac->CreateDeviceInstance());
            std::string dummyOut;
            devIns->InternalHandler(state[i], dummyOut, flag);
        } else if (std::string(devInfo->devTypeId) == THING_MODEL_CONTROL) {
            std::shared_ptr<AbstractFactory> devFac = std::make_shared<ControlFactory>();
            std::shared_ptr<AbstractDevice> devIns(devFac->CreateDeviceInstance());
            std::string dummyOut;
            devIns->InternalHandler(state[i], dummyOut, flag);
        }
    }
#endif
    return SLE_BRIDGE_SUCCESS;
}

static int32_t PutCharState(const IotcCharState state[], uint32_t num)
{
    DEMO_LOG("PutCharState in");
    if (state == NULL || num <= 0) {
        DEMO_LOG("param invalid, num=%{public}d", num);
        return SLE_BRIDGE_FAILED;
    }

    std::vector<std::string> dummyOut;  // 不需要输出数据
    return IotcDataHandler(state, num, dummyOut, ThingModelPutOrGet::PUT);
}

static int32_t GetCharState(const IotcCharState state[], char *out[], uint32_t len[], uint32_t num)
{
    DEMO_LOG("GetCharState in");
    if (state == NULL || num == 0 || out == NULL || len == NULL) {
        DEMO_LOG("param invalid");
        return SLE_BRIDGE_FAILED;
    }

    std::vector<std::string> stringOut;
    int32_t ret = IotcDataHandler(state, num, stringOut, ThingModelPutOrGet::GET);

    // 将 std::string 转换为 char* 输出
    for (uint32_t i = 0; i < num && i < stringOut.size(); ++i) {
        if (!stringOut[i].empty()) {
            out[i] = new char[stringOut[i].length() + 1];
            errno_t copyResult = strcpy_s(out[i], stringOut[i].length() + 1, stringOut[i].c_str());
            if (copyResult != 0) {
                delete[] out[i];
                out[i] = nullptr;
                len[i] = 0;
                HILOGE("strcpy_s failed for index %{public}u, error: %{public}d", i, copyResult);
                return SLE_BRIDGE_FAILED;
            }
            len[i] = stringOut[i].length();
        } else {
            out[i] = nullptr;
            len[i] = 0;
        }
    }

    return ret;
}

static int32_t ReportAll()
{
    DEMO_LOG("ReportAll in");

    uint8_t svcNumStation = mapThingModelSvcStation.size();
    IotcCharState outData[svcNumStation];
    int32_t ret = 0;

    std::shared_ptr<AbstractFactory> devFac = std::make_shared<ControlFactory>();
    std::shared_ptr<AbstractDevice> devIns(devFac->CreateDeviceInstance());
    devIns->GetAllInfoHandler("", outData);

    ret = IotcOhDevReportCharState(outData, svcNumStation);
    if (ret != 0) {
        HILOGE("IotcOhDevReportCharState error");
        return SLE_BRIDGE_FAILED;
    }
    return ret;
}

static int32_t ReportAllByDevid(const char *devId)
{
    DEMO_LOG("ReportAllByDevid in");

    int32_t ret = 0;

    IotcDeviceInfo devInfo;
    ret = IotcOhFindDeviceInfo(devId, (void **)&devInfo);
    if (0 != ret) {
        DEMO_LOG("get devTypeId error, code:%{public}d", ret);
        return SLE_BRIDGE_FAILED;
    }

    if (std::string(devInfo.devTypeId) == THING_MODEL_LEAKER) {
        std::shared_ptr<AbstractFactory> devFac = std::make_shared<ControlFactory>();
        std::shared_ptr<AbstractDevice> devIns(devFac->CreateDeviceInstance());
        devIns->GetAllInfoHandler(devId, nullptr);
    } else if (std::string(devInfo.devTypeId) == THING_MODEL_CONTROL) {
        std::shared_ptr<AbstractFactory> devFac = std::make_shared<ControlFactory>();
        std::shared_ptr<AbstractDevice> devIns(devFac->CreateDeviceInstance());
        devIns->GetAllInfoHandler(devId, nullptr);
    } else {
        HILOGE("no define devTpye, devTpye:%{public}s", devInfo.devTypeId);
    }

    return ret;
}

void HandleStatusIndicator(const IotcJson *dataObj, const char *sid)
{
    IotcJson *indicatorNode = IotcJsonGetObj(dataObj, "statusIndicator");
    if (!indicatorNode || !IotcJsonIsNum(indicatorNode)) {
        return;
    }

    int64_t indicator = 0;
    if (IotcJsonGetNum(indicatorNode, &indicator) != 0) {
        return;
    }

    if (indicator != 1) {
        return;
    }

    // 燃气告警处理，判断是否包含 gasLeakEscalationValue 字段
    IotcJson *escalationNode = IotcJsonGetObj(dataObj, "gasLeakEscalationValue");
    if (escalationNode != nullptr && IotcJsonIsNum(escalationNode)) {
        // 是 gasLeakEscalationValue，找 GAS-LEAK-DETECTOR-01
        IotcConDeviceInfo *devInfo = NULL;
        int ret = IotcOhFindDeviceInfoByName("GAS-CONTROL-VALVES-01", &devInfo);
        if (ret != 0 || devInfo == nullptr) {
            DEMO_LOG("get gas leak detector info error, code:%{public}d", ret);
            return;
        }

        // 上报状态
        std::string dataStr = IotcJsonPrint(dataObj);
        if (!dataStr.empty()) {
            IotcCharState reportInfo;
            reportInfo.svcId = sid;
            reportInfo.len = dataStr.length();
            reportInfo.data = dataStr.c_str();
#if IOTC_CONF_DEV_TYPE == 2
            reportInfo.devId = devInfo->devId; // 补充 devId
            reportInfo.msgId = NULL; // 可选字段，若无 msgId 可设为 NULL
#endif
            int reportResult = IotcOhDevReportCharState(&reportInfo, 1);
            if (reportResult != 0) {
                HILOGE("IotcOhDevReportCharState error");
            }
        }

        std::shared_ptr<ControlValue> devIns = std::make_shared<ControlValue>();
        ret = devIns->switchGasValue(devInfo->devId, false);
        if (ret != SLE_BRIDGE_SUCCESS) {
            return;
        }
    }
}

int32_t RecvCustomSecData(const uint8_t *data, uint32_t len)
{
    std::string dataStr(static_cast<const char*>(static_cast<const void*>(data)), len);
    IotcJson *root = IotcJsonParseWithLen(dataStr.c_str(), len);

    if (root == nullptr) {
        HILOGE("create json error");
        return SLE_BRIDGE_FAILED;
    }

    if (!IotcJsonIsArray(root)) {
        HILOGE("root is not array");
        return SLE_BRIDGE_FAILED;
    }

    uint32_t arraySize = 0;
    int32_t ret = IotcJsonGetArraySize(root, &arraySize);
    if (ret != 0 || arraySize == 0) {
        HILOGE("get array size fail");
        return SLE_BRIDGE_FAILED;
    }

    for (uint32_t i = 0; i < arraySize; ++i) {
        IotcJson *element = IotcJsonGetArrayItem(root, i);
        if (element == nullptr) {
            continue;
        }

        IotcJson *sidNode = IotcJsonGetObj(element, "sid");
        const char *sid = IotcJsonGetStr(sidNode);
        if (sid != nullptr && strcmp(sid, "serviceList") == 0) {
            IotcJson *dataObj = IotcJsonGetObj(element, "data");
            HandleStatusIndicator(dataObj, sid);
        }
    }

    return SLE_BRIDGE_SUCCESS;
}

static int32_t GetPincode(uint8_t *buf, uint32_t bufLen)
{
    DEMO_LOG("GetPincode in");
    if (buf == NULL || bufLen > IOTC_PINCODE_LEN) {
        DEMO_LOG("param invalid");
        return -1;
    }

#if IOTC_CONF_AILIFE_SUPPORT
    /*
    unsigned char pskBuf[HILINK_PSK_LEN] = {0};
    extern void HiLinkGetPsk(unsigned char *psk, unsigned short len);
    HiLinkGetPsk(pskBuf, HILINK_PSK_LEN);

    int32_t ret = memcpy_s(buf, bufLen, pskBuf, PINCODE_LEN);
    */
    int32_t ret = memcpy_s(buf, bufLen, PIN_CODE, strlen(PIN_CODE));
#else
    int32_t ret = memcpy_s(buf, bufLen, PIN_CODE, strlen(PIN_CODE));
#endif
    if (ret != EOK) {
        return -1;
    }
    return 0;
}

static int32_t GetAcKey(uint8_t *buf, uint32_t bufLen)
{
    DEMO_LOG("GetAcKey in");
    if (buf == NULL || bufLen > IOTC_AC_KEY_LEN) {
        DEMO_LOG("param invalid");
        return -1;
    }
    int32_t ret = memcpy_s(buf, bufLen, AC_KEY, sizeof(AC_KEY));
    if (ret != EOK) {
        return -1;
    }
    return 0;
}

#if IOTC_CONF_AILIFE_SUPPORT
#define HILINK_HTTPS_CERT1                                                 \
    "-----BEGIN CERTIFICATE-----\r\n"                                      \
    "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\r\n"         \
    "-----END CERTIFICATE-----\r\n"

#define HILINK_HTTPS_CERT14                                                \
    "-----BEGIN CERTIFICATE-----\r\n"                                      \
    "MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\r\n" \
    "A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\r\n" \
    "Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\r\n" \
    "MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\r\n" \
    "A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\r\n" \
    "hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\r\n" \
    "RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\r\n" \
    "gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\r\n" \
    "KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\r\n" \
    "QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\r\n" \
    "XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\r\n" \
    "DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\r\n" \
    "LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\r\n" \
    "RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\r\n" \
    "jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\r\n" \
    "6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\r\n" \
    "mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\r\n" \
    "Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\r\n" \
    "WD9f\r\n"                                                             \
    "-----END CERTIFICATE-----\r\n"

#define HILINK_HTTPS_CERT28                                                \
    "-----BEGIN CERTIFICATE-----\r\n"                                      \
    "MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD\r\n" \
    "TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y\r\n" \
    "aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx\r\n" \
    "MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j\r\n" \
    "aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP\r\n" \
    "T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03\r\n" \
    "sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL\r\n" \
    "TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5\r\n" \
    "/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp\r\n" \
    "7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz\r\n" \
    "EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt\r\n" \
    "hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP\r\n" \
    "a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot\r\n" \
    "aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg\r\n" \
    "TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV\r\n" \
    "PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv\r\n" \
    "cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL\r\n" \
    "tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd\r\n" \
    "BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB\r\n" \
    "ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT\r\n" \
    "ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL\r\n" \
    "jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS\r\n" \
    "ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy\r\n" \
    "P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19\r\n" \
    "xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d\r\n" \
    "Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN\r\n" \
    "5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe\r\n" \
    "/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z\r\n" \
    "AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ\r\n" \
    "5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su\r\n"                     \
    "-----END CERTIFICATE-----\r\n"
#endif

static int32_t GetRootCA(const char **ca[], uint32_t *num)
{
    if (ca == nullptr || num == nullptr) {
        DEMO_LOG("param invalid");
        return -1;
    }
    /* 填充证书*/
#if IOTC_CONF_AILIFE_SUPPORT
    static const char *CA_CERT[] = {HILINK_HTTPS_CERT1, HILINK_HTTPS_CERT14, HILINK_HTTPS_CERT28};
#else
    static const char *CA_CERT[] = {NULL};
#endif

    *ca = CA_CERT;
    *num = sizeof(CA_CERT) / sizeof(CA_CERT[0]);
    return 0;
}

static void DemoBleEventListener(int32_t event)
{
    switch (event) {
        case IOTC_CORE_COMM_EVENT_MAIN_INITIALIZED:
            EnableBt();
            usleep(DELAY_MS);
            EnableBle();
            usleep(DELAY_MS);
            break;
        default:
            return;
    }
}

static int32_t NoticeReboot(IotcRebootReason res)
{
    DEMO_LOG("notice reboot res %{public}d", res);
    return 0;
}

#define SET_OH_SDK_OPTION(ret, option, ...)                                      \
    do {                                                                         \
        (ret) = IotcOhSetOption((option), __VA_ARGS__);                          \
        if ((ret) != 0) {                                                        \
            DEMO_LOG("set option %{public}d error %{public}d", (option), (ret)); \
        }                                                                        \
    } while (0);

static int32_t MakeOsBleEnable(void)
{
    int32_t ret = IOTC_OK;
    if (IsBleEnabled() == false) {
        if (EnableBle() == false) {
            IOTC_LOGE("enable ble fail");
            ret = IOTC_ERROR;
        } else {
            IOTC_LOGI("enable ble ok");
        }
    }
    /* 此处加延时为了使后面SetLocalName可以成功执行 */
    sleep(2);
    return ret;
}

static int32_t MakeOsWifiEnable(void)
{
    int32_t ret = IOTC_OK;
    if (IsWifiActive() != WIFI_STA_ACTIVE) {
        if (EnableWifi() != WIFI_SUCCESS) {
            IOTC_LOGE("enable wifi fail");
            ret = IOTC_ERROR;
        } else {
            IOTC_LOGI("enable wifi ok");
        }
    }
    return ret;
}

int32_t IotcOhDemoEntry(void)
{
    const char *serial = AclGetSerial();
    DEV_INFO.sn = strdup(serial);
    int32_t ret = IotcOhDevInit();
    if (ret != 0) {
        return ret;
    }
    ret = IotcOhBleEnable();
    if (ret != 0) {
        return ret;
    }
    ret = IotcOhWifiEnable();
    if (ret != 0) {
        return ret;
    }
    ret = IotcOhSleEnable();
    if (ret != 0) {
        return ret;
    }
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_PUT_CHAR_STATE_CALLBACK, PutCharState);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_GET_CHAR_STATE_CALLBACK, GetCharState);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_REPORT_ALL_CALLBACK, ReportAll);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_SLE_REPORT_BY_DEVID_CALLBACK, ReportAllByDevid);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_SLE_RECV_CUSTOM_DATA_CALLBACK, RecvCustomSecData);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_GET_PINCODE_CALLBACK, GetPincode);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_GET_AC_KEY_CALLBACK, GetAcKey);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_REBOOT_CALLBACK, NoticeReboot);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_DEV_INFO, &DEV_INFO);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_SVC_INFO, SVC_INFO, sizeof(SVC_INFO) / sizeof(SVC_INFO[0]));
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_BLE_START_UP_ADV_TIMEOUT, (1000 * 60 * 1000));
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_SDK_REG_EVENT_LISTENER, DemoBleEventListener);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_SDK_CONFIG_PATH, "/data/app/iotc");
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_BLE_ENABLE_FUNC_CALLBACK, MakeOsBleEnable);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_WIFI_ENABLE_FUNC_CALLBACK, MakeOsWifiEnable);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_WIFI_GET_CERT_CALLBACK, GetRootCA);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_WIFI_NETCFG_MODE, IOTC_NET_CONFIG_MODE_BLE_SUP);
    SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_WIFI_NETCFG_TIMEOUT, (10 * 60 * 1000));
#ifdef USE_MANUAL_PSK_DEVID_CODE_PARAM_IMPORT_WAY_DEBUG
    // /* 如传入固定参数，则写死配置psk，code，devInfo云端注册设备信息*/
    if (g_devRegInfo.devId[0]) {
        SET_OH_SDK_OPTION(ret, IOTC_OH_OPTION_DEVICE_TEST_REGISTER_CLOUD_DEV_INFO, &g_devRegInfo);
    }
#endif
    ret = IotcOhMain();
    if (ret != 0) {
        return ret;
    }
    return ret;
}

void IotcOhDemoExit(void)
{
    int32_t ret = IotcOhStop();
    if (ret != 0) {
        DEMO_LOG("iotc stop error %{public}d", ret);
    }

    ret = IotcOhSetOption(IOTC_OH_OPTION_SDK_UNREG_EVENT_LISTENER, DemoBleEventListener);
    if (ret != 0) {
        DEMO_LOG("unreg event listener error %{public}d", ret);
    }

    ret = IotcOhSleDisable();
    if (ret != 0) {
        DEMO_LOG("iotc wifi disable error %{public}d", ret);
    }

    ret = IotcOhWifiDisable();
    if (ret != 0) {
        DEMO_LOG("iotc wifi disable error %{public}d", ret);
    }

    ret = IotcOhBleDisable();
    if (ret != 0) {
        DEMO_LOG("iotc wifi disable error %{public}d", ret);
    }

    ret = IotcOhDevDeinit();
    if (ret != 0) {
        DEMO_LOG("iotc dev info deinit error %{public}d", ret);
    }
}

void PressButton1(void)
{
    DEMO_LOG("button 1 press");
    IotcOhRestore();
}

void PressButton2(void)
{
    DEMO_LOG("button 2 press");
    IotcOhDemoExit();
}

} // namespace iotConnect
} // namespace OHOS